// app/server/clientServer.js
const { app } = require('electron');
const express = require('express');
// const http = require('http');
const WebSocket = require('ws');
const path = require('path');

const colors = require('colors');

const cors = require('cors');
const bodyParser = require('body-parser');
const logger = require('@utils/logger')
const nettools = require('@utils/network');
const fileHandle = require('@utils/fileHandle');
const gs = require('@utils/globalStore');
const { activityApi } = require('@api/activityApi')
const { isDev } = require('@utils/helper')

async function createAppServer() {
    const sr = gs.get('clientServer');
    if (sr) return sr

    const httpService = express()

    // 跨域设置
    httpService.use(cors({
        origin: '*',
        methods: 'GET,POST,PUT,DELETE',
        allowedHeaders: 'Content-Type,Authorization,x_project_id',
        optionsSuccessStatus: 204
    }))

    // 使用 express.json() 或 express.urlencoded() 解析请求体;;;增加请求体大小限制到50MB
    httpService.use(bodyParser.json({ limit: '50mb' }));
    httpService.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));

    // 设置静态文件目录（指向客户端打包后的dist目录）
    const clientDistPath = fileHandle.getClientDistPath(); // 客户端或者界面 server，web root 为编译后的 dist
    const resourceRoot = fileHandle.getResourceRoot(); // 所有静态资源的目录，为 userData 下的 uploads

    httpService.use(express.static(clientDistPath));
    httpService.use('/assets', express.static(resourceRoot));

    // 生产环境托管静态文件（开发环境用vite服务）
    let staticPath = isDev() ? path.join(process.resourcesPath, 'dist') : path.join(app.getAppPath(), '../dist')

    console.log('static path'.bgBlack, staticPath.red);

    httpService.use(express.static(staticPath))

    console.log(`[+10005]before create client server, test web root::${clientDistPath}`.bgWhite);
    logger.info(`[+10005]client Server assets path::${resourceRoot}`.red);

    // 创建 HTTP 服务器
    const port = gs.getServerPort();    // 从配置文件或默认变量中读取端口
    let maxAttempts = 10;    // 最大尝试次数

    testAPI(httpService);
    activityApi(httpService);

    const httpServer = await startServerWithPortCheck(httpService, port, maxAttempts);
    if (httpServer) {

        logger.info(`[+10007]client Server launch at ::${nettools.getLocalIP()}:${port}`);
    } else {
        logger.error('[+10008]client Server launch Failed');
    }

    // WebSocket逻辑
    const wss = new WebSocket.Server({ server: httpServer })
    wss.on('connection', (ws) => {
        ws.on('message', (msg) => {
            const data = JSON.parse(msg)

            // 广播消息给所有客户端
            wss.clients.forEach((client) => {
                if (client.readyState === WebSocket.OPEN) {
                    client.send(JSON.stringify(data))
                }
            })

            // 如果是复制操作，保存到数据库
            if (data.type === 'get-server-ip') {
                ws.send(JSON.stringify({
                    type: 'repy-server-ip',
                    ip: nettools.getLocalIP()
                }))
            }

            console.log(`[WS] Received: ${data}`)
            // ws.send(`Server回应: ${data}`)
        })
    })

    gs.set('clientServer', { httpServer, port });

    return {
        httpServer,
        port: 3900 // 统一端口
    }
}

/**
 * 启动服务器并检查端口占用
 */
async function startServerWithPortCheck(app, port, maxAttempts = 10) {
    while (maxAttempts > 0) {
        if (await nettools.isPortFree(port)) {
            return app.listen(port, '0.0.0.0');
        }
        logger.warn(`[+10007]端口 ${port} 被占用，尝试下一个端口...`);
        port++;
        maxAttempts--;
    }
    throw new Error('[+10007]无法找到可用端口');
}

/**
 * 如果客户端服务已开启，则安全关闭
 */
function serverClose() {
    if (gs.has('clientServer')) {
        const { server, port } = gs.get('clientServer')
        server.close(() => {
            logger.info(`[+10017]client Server closed at ${port}`)
        });
    }
}

const testAPI = (server) => {

    // 客户端：客户端测试接口
    server.get('/api/test', (req, res) => {
        const ret = { name: 'zhangsan', age: 19, married: false }
        res.json(ret)
    });
}

module.exports = {
    createAppServer,
    serverClose,
}